package org.j4me.info;

import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.util.Hashtable;
import java.util.Vector;

import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Display;
import javax.microedition.midlet.MIDlet;
import javax.microedition.rms.RecordStore;

import org.j4me.logging.Level;
import org.j4me.logging.Log;
import org.j4me.ui.UIManager;
import org.j4me.ui.components.ProgressBar;

public class DeviceInfo {
	Vector _keys = new Vector();
	Vector _values = new Vector();
	private static boolean _blackberry;
	private static boolean _tao;
	private static boolean _ibmJ9;
	private static boolean _midp2;
	private static boolean _midp1;
	private static boolean _nokia;
	private static boolean _esmertecJbed;
	private static boolean sonyEricsson;
	static {
		// Check if running on a BlackBerry.
		_blackberry = hasClass("net.rim.device.api.ui.UiApplication").booleanValue();
		_ibmJ9 = hasClass("java.lang.J9VMInternals").booleanValue();
		String platform = System.getProperty("microedition.platform");
		if (platform.indexOf("intent") > -1)
			_tao = true;
		else if (platform.indexOf("Nokia") > -1)
			_nokia = true;
		else if (platform.indexOf("SonyEricsson") > -1)
			sonyEricsson = true;
		else if (platform.indexOf("Jbed") > -1)
			_esmertecJbed = true;
		String profile = System.getProperty("microedition.profiles");
		if (profile.startsWith("MIDP-1."))
			_midp1 = true;
		else if (profile.startsWith("MIDP-2."))
			_midp2 = true;
	}

	public DeviceInfo(MIDlet app) {
		put("Version",app.getAppProperty("Midlet-version"));
	}

	static public boolean isTao() {
		return _tao;
	}

	static public boolean isJ9() {
		return _ibmJ9;
	}

	static public boolean isNokia() {
		return _nokia;
	}

	static public boolean isSonyEricsson() {
		return sonyEricsson;
	}

	static public boolean isBlackBerry() {
		return _blackberry;
	}
	
	static public boolean isEsmertecJbed() {
		return _esmertecJbed;
	}

	static public boolean isMIDP2() {
		return _midp2;
	}

	static public boolean isMIDP1() {
		return _midp1;
	}

	/**
	 * Populates the the collection  with details about the current device.
	 * 
	 */
	public void collect() {
		Log.setLevel(Level.DEBUG);
		Display display = UIManager.getDisplay();
		put("KVM", getKVMName());
		put("screenWidth", new Integer(display.getCurrent().getWidth()));
		put("screenHeight", new Integer(display.getCurrent().getHeight()));
		put("numColor", new Integer(display.numColors()));
		put("grayLevel", new Boolean(!display.isColor()));
		if (isMIDP2())
			put("alphaLevel", new Integer(display.numAlphaLevels()));
		putProperty("microedition.platform");
		putProperty("microedition.configuration");
		putProperty("microedition.profiles");
		//putProperty("microedition.locale");
		//putProperty("microedition.encoding");
		putProperty("microedition.commports");
		//putProperty("microedition.hostname");
	
		put("JSR_238", hasClass("javax.microedition.global.Formatter"));
		put("JSR_229", hasClass("javax.microedition.payment.TransactionRecord"));
		put("JSR_177", hasClass("java.security.Signature"));
		put("JSR_234", hasClass("javax.microedition.amms.GlobalManager"));
		put("JSR_226", hasClass("javax.microedition.m2g.ScalableGraphics"));
		put("JSR_184", hasClass("javax.microedition.m3g.Node"));
		put("JSR_135", hasClass("javax.microedition.media.Manager"));
		put("JSR_135_Video", hasClass("javax.microedition.media.TimeBase"));
		put("JSR_180", hasClass("javax.microedition.sip.SipConnection"));
		put("JSR_205", hasClass("javax.wireless.messaging.MessagePart"));
		put("JSR_82", hasClass("javax.bluetooth.LocalDevice"));
		put("JSR_82_Obex", hasClass("javax.obex.HeaderSet"));
		put("JSR_120", hasClass("javax.wireless.messaging.Message"));
		put("JSR_179", hasClass("javax.microedition.location.Location"));
		put("JSR_75_PIM", hasClass("javax.microedition.pim.PIM"));
		put("JSR_75_File", hasClass("javax.microedition.io.file.FileConnection"));
		put("JSR_211", hasClass("javax.microedition.content.Invocation"));
		put("JSR_172", hasClass("javax.xml.parsers.SAXParser"));
		put("NokiaUI", hasClass("com.nokia.mid.ui.DeviceControl"));
	}

	private String getKVMName() {
		if (isBlackBerry())
			return "BlackBerry";
		else if (isTao())
			return "Tao Intent";
		else if (isJ9())
			return "IBM J9";
		else if (isNokia())
			return "Nokia";
		else if (isSonyEricsson())
			return "SonyEricsson";
		return "Unknown";
	}

	public void collectMoreInfo() {
//		try {
//			RecordStore store = RecordStore.openRecordStore("test", true);
//			put("device.availableRms", new Long(store.getSizeAvailable()));
//			store.closeRecordStore();
//		} catch (Throwable t) {
//		} finally {
//			try {
//				RecordStore.deleteRecordStore("test");
//			} catch (Throwable t) {
//			}
//		}
//		put("device.totalMemory", new Long(Runtime.getRuntime().totalMemory()));
//		putProperty("fileconn.dir.memorycard.name");
		
		putProperty("microedition.io.file.FileConnection.version");
		putProperty("file.separator");
		putProperty("microedition.pim.version");
		
		if (hasClass("javax.microedition.media.Manager").booleanValue()) {
			String[] types = javax.microedition.media.Manager.getSupportedContentTypes(null);
			put("MediaContent", types);
			for (int i = 0; i < types.length; i++) {
				String[] protocols = javax.microedition.media.Manager.getSupportedProtocols(types[i]);
				put("MediaProtocol_" + types[i], protocols);
			}
			putProperty("microedition.media.version");
			putProperty("supports.audio.capture");
			putProperty("supports.video.capture");
			putProperty("audio.encodings");
			putProperty("video.encodings");
			putProperty("video.snapshot.encoding");
		}
	}

	private void putProperty(String prop) {
		put (prop, System.getProperty(prop));
		
	}

	public void collectCanvasInfo(ProgressBar bar) {
		Display display = UIManager.getDisplay();
		int min = 2 * Short.MIN_VALUE;
		int offset = min * -1;
		int max = 2 * Short.MAX_VALUE;
		bar.setMaxValue(max + offset);
		bar.repaint();
		if (display.getCurrent() instanceof Canvas) {
			Canvas canvas = (Canvas) display.getCurrent();
			put("doubleBuffered", new Boolean(canvas.isDoubleBuffered()));
			put("pointerEvents", new Boolean(canvas.hasPointerEvents()));
			put("pointerMotionEvents", new Boolean(canvas.hasPointerMotionEvents()));
			put("keyRepeatEvents", new Boolean(canvas.hasRepeatEvents()));
			for (int keyCode = min; keyCode < max; keyCode++) {
				try {
					if (keyCode % 100 == 0) {
						bar.setValue(keyCode + offset);
						bar.repaint();
					}
					String keyName = canvas.getKeyName(keyCode);
					if(keyName != null) // remove unexpected char
					{
						boolean update = false;
						char [] keyNameArray = keyName.toCharArray();
						for(int i=0; i < keyNameArray.length;i++)
						{
							if(keyNameArray[i] < ' ') {
								keyNameArray[i]  = ' ';
								update = true;
							}
						}
						if(update)
							keyName = new String(keyNameArray).trim();
					}
					int action = 0;
					try {
						action = canvas.getGameAction(keyCode);
					} catch (Throwable t1) {
					}
					if (action > 0 || (action >= 0 && keyName != null && -100 < keyCode && keyCode < 100) || isSoftKey(keyName))
						put("K[" + keyCode + "]", new Object[] { new Integer(action), keyName });
				} catch (Throwable t) {
				}
			}
		}
	}

	private boolean isSoftKey(String keyName) {
		if (keyName != null) {
			String key = keyName.toLowerCase();
			return key.indexOf("soft") >= 0 || key.indexOf("left") >= 0 || key.indexOf("right") >= 0;
		}
		return false;
	}

	private void put(String key, Object value) {
		if (value != null && key != null) {
			_keys.addElement(key);
			_values.addElement(value);
			//_values.addElement(value);
		}
	}
	
	

	/**
	 * Determines if a class is available or not.  This can be used to see
	 * what libraries are running on the system.
	 *
	 * @param name is the fullly qualified name of a class.
	 * @return <code>true</code if the class exists and <code>false</code> if it
	 *  does not.
	 */
	public static Boolean hasClass(String name) {
		try {
			Class.forName(name);
			return new Boolean(true);
		} catch (Throwable e) {
			return new Boolean(false);
		}
	}

	

	public int getCount() {
		return _keys.size();
	}

	public String getKey(int idx) {
		return (String) _keys.elementAt(idx);
	}

	public Object getValue(int idx) {
		return _values.elementAt(idx);
	}

	public String getStringValue(int idx) {
		Object value = getValue(idx);
		if (value instanceof Object[]) {
			Object[] array = (Object[]) value;
			String result = "{";
			for (int i = 0; i < array.length; i++) {
				if (i != 0)
					result += "," + array[i].toString();
				else
					result += array[i].toString();
			}
			result += "}";
			return result;
		}
		return value.toString();
	}

	public void setBrand(String value) {
		put("brand", value);
		
	}
	public void setModel(String value) {
		put("model", value);
		
	}
	public void setOperator(String value) {
		put("operator", value);
		
	}
}
